#pragma once
#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <unistd.h>
#include <functional>
#include "Mythread.hpp"

using namespace ThreadClass;
static int DEFAULTNUM = 10;

template <typename T>
class ThreadPool
{
private:
    // 保护任务队列
    void LockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }
    // 解锁
    void UnlockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void WakeUp()
    {
        pthread_cond_signal(&_cond);
    }
    void WakeUpAll()
    {
        pthread_cond_broadcast(&_cond);
    }
    bool IsEmpty()
    {
        return _task_queue.empty();
    }
    void ThreadSleep()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    void HandlerTask()
    {
        while (true)
        {
            LockQueue();
            while (IsEmpty() && _isRunning == true)
            {
                // 线程休眠
                _sleep_thread_num++;
                ThreadSleep();
                _sleep_thread_num--;
            }
            // 判断是否stop线程池
            if (IsEmpty() && _isRunning == false) // 注意点 -->stop条件
            {
                UnlockQueue();
                break;
            }
            T task = _task_queue.front();
            _task_queue.pop();
            UnlockQueue();
            // 处理任务
            task();
        }
    }

public:
    ThreadPool(int maxnum = DEFAULTNUM) : _MaxNum(maxnum), _isRunning(false), _sleep_thread_num(0)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }
    void Init()
    {
        // 技巧--> bind配合function<>
        func_t func = std::bind(&ThreadPool::HandlerTask, this); // 占位符表示自动推导剩余参数类型

        for (int i = 0; i < _MaxNum; i++)
        {
            std::string thread_name = "thread" + std::to_string(i + 1);
            _threads.emplace_back(thread_name, func);
        }
    }
    void start()
    {
        _isRunning = true;
        for (auto &thread : _threads)
        {
            thread.Start();
        }
    }
    void Push(const T &Task)
    {
        LockQueue();
        // 只有线程池处于启动状态才能push任务
        if (_isRunning == true)
        {
            _task_queue.push(Task);
            if (_sleep_thread_num > 0)
            {
                // 有线程休眠就唤醒
                WakeUp();
            }
        }
        UnlockQueue();
    }
    void Stop()
    {
        LockQueue();
        _isRunning = false;
        // 注意点-->要唤醒线程池中所有的线程！防止handler死循环
        WakeUpAll();
        UnlockQueue();
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

private:
    int _MaxNum; // 线程池中的线程最大数量
    std::vector<Thread> _threads;
    std::queue<T> _task_queue; // 任务队列
    bool _isRunning;
    int _sleep_thread_num; // 池中休眠的线程个数
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
};